import torch


# todo view 和 contiguous 方法
#   1. view 方法
# 创建一个一维张量
tensor_1d = torch.arange(12)
print("原始一维张量:", tensor_1d)
print("原始一维张量形状:", tensor_1d.shape)

# 使用 view 方法将其转换为 3 行 4 列的二维张量
tensor_2d = tensor_1d.view(3, 4)
print("\n转换后的二维张量:")
print(tensor_2d)
print("转换后的二维张量形状:", tensor_2d.shape)

#  todo 2. contiguous 方法
# 创建一个二维张量
tensor = torch.arange(12).view(3, 4)
print("原始二维张量形状:", tensor.shape)

# 对张量进行转置操作，转置后的张量可能不连续
transposed_tensor = tensor.t()
print("转置后的张量是否连续:", transposed_tensor.is_contiguous())

try:
    # 尝试对不连续的张量使用 view 方法，会报错
    new_tensor = transposed_tensor.view(2, 6)
except RuntimeError as e:
    print(f"报错信息: {e}")

# 使用 contiguous 方法使张量连续
contiguous_tensor = transposed_tensor.contiguous()
print("使用 contiguous 后的张量是否连续:", contiguous_tensor.is_contiguous())

# 现在可以对连续的张量使用 view 方法
new_tensor = contiguous_tensor.view(2, 6)

# todo 总结
#   1. view 方法用于修改张量的形状，但不会修改张量元素的内存，如果新张量的形状与原张量不兼容，就会报错
#   2. contiguous 方法用于让张量在内存中连续存储，从而可以将其转换为 CPU 或 GPU 上的 Tensor，还可以使用 view 方法
#   3. 如果张量是连续存储的，那么 contiguous 方法返回原张量，否则会返回一个新张量，并且原张量的形状会变成新张量的形状
#   4. 如果张量不是连续存储的，那么使用 view 方法会报错，但使用 contiguous 方法可以将其转换为连续存储的
#   5. 如果需要经常对张量进行转置，那么最好将其转换为连续存储的形式，从而避免重复调用 contiguous 方法
#   view 方法用于改变张量的形状，不复制数据，共享底层内存。
#   contiguous 方法用于确保张量在内存中连续存储，以便支持某些对连续性有要求的操作（如 view）。